package com.mmall.controller.portal;

import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.demo.trade.config.Configs;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Maps;
import com.mmall.common.IConst;
import com.mmall.common.ResponseInfo;
import com.mmall.common.ServerResponse;
import com.mmall.pojo.User;
import com.mmall.service.IOrderService;
import com.mmall.vo.OrderProductVo;
import com.mmall.vo.OrderVo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.Map;

/**
 * 订单管理及支付宝管理控制层
 * Created by qezhhnjy on 2017/10/6-15:15.
 */
@Controller
@RequestMapping("/order/")
public class OrderController {

    private static final Logger logger = LoggerFactory.getLogger(OrderController.class);

    @Resource
    private IOrderService iOrderService;

    /**
     * 通过订单信息生成可扫码支付的二维码图片
     *
     * @param session 当前会话
     * @param orderNo 订单号
     * @param request 请求对象
     * @return 封装二维码图片的nginx代理DNS地址信息的响应对象
     */
    @ResponseBody
    @RequestMapping(value = "pay.do", method = RequestMethod.POST)
    public ServerResponse pay(HttpSession session, Long orderNo, HttpServletRequest request) {
        User user = (User) session.getAttribute(IConst.CURRENT_USER);
        if (user == null)
            return ServerResponse.createByErrorCode(ResponseInfo.NEED_LOGIN.getCode(), ResponseInfo.NEED_LOGIN.getDescription());
        String path = request.getSession().getServletContext().getRealPath("upload");
        return iOrderService.pay(user.getId(), orderNo, path);
    }

    /**
     * 支付宝异步回调通知.
     *
     * @param request 当前请求,指支付宝返回的包含所有回调信息的请求
     * @return 返回支付宝需要的"success"/"failed"响应
     */
    @ResponseBody
    @RequestMapping(value = "alipay_callback.do", method = RequestMethod.POST)
    public Object alipayCallback(HttpServletRequest request) {
        Map<String, String> tempMap = Maps.newHashMap();
        Map<String, String[]> requestMap = request.getParameterMap();

        //将request中参数集合的value由字符串数组转换为逗号分隔开的字符串.
        for (String s : requestMap.keySet()) {
            String[] values = requestMap.get(s);
            StringBuilder tempValue = new StringBuilder();
            for (String value : values) tempValue.append(value).append(",");
            tempValue.deleteCharAt(tempValue.lastIndexOf(","));
            System.out.println(s + ":" + tempValue);
            tempMap.put(s, tempValue.toString());
        }
        logger.info("支付宝回调,sign:{},trade_status:{},参数:{}", tempMap.get("sign"), tempMap.get("trade_status"), tempMap.toString());

        //非常重要,验证回调的正确性,是不是支付宝发的,并且还要避免重复通知.
        //这里可以参照蚂蚁金服官网上的方法及源码进行回调的验证
        tempMap.remove("sign_type");
        try {
            boolean checkV2 = AlipaySignature.rsaCheckV2(tempMap, Configs.getAlipayPublicKey(), "utf-8", Configs.getSignType());

            if (!checkV2) return ServerResponse.createByErrorMessage("非法请求,验证不通过!~");

        } catch (AlipayApiException e) {
            logger.error("支付宝验证回调异常~!", e);
        }

        //todo 验证各种商品数据

        ServerResponse sr = iOrderService.aliCallback(tempMap);
        if (sr.isSuccess())
            return IConst.AlipayCallback.RESPONSE_SUCCESS;
        return IConst.AlipayCallback.RESPONSE_FAILED;
    }

    /**
     * 查询订单状态
     *
     * @param session 当前用户
     * @param orderNo 订单号
     * @return 订单是否已经付款
     */
    @ResponseBody
    @RequestMapping(value = "query_order_pay_status.do", method = RequestMethod.POST)
    public ServerResponse<Boolean> queryOrderPayStatus(HttpSession session, Long orderNo) {
        User user = (User) session.getAttribute(IConst.CURRENT_USER);
        if (user == null)
            return ServerResponse.createByErrorCode(ResponseInfo.NEED_LOGIN.getCode(), ResponseInfo.NEED_LOGIN.getDescription());
        return ServerResponse.createBySuccess(iOrderService.queryOrderPayStatus(user.getId(), orderNo).isSuccess());
    }

    /**
     * 生成订单
     *
     * @param session    当前用户
     * @param shippingId 指定的收货地址
     * @return 响应对象，其中包含完整的订单VO对象。
     */
    @ResponseBody
    @RequestMapping(value = "create.do", method = RequestMethod.POST)
    public ServerResponse create(HttpSession session, Integer shippingId) {
        User user = (User) session.getAttribute(IConst.CURRENT_USER);
        if (user == null)
            return ServerResponse.createByErrorCode(ResponseInfo.NEED_LOGIN.getCode(), ResponseInfo.NEED_LOGIN.getDescription());
        return iOrderService.createOrder(user.getId(), shippingId);
    }

    /**
     * 取消用户的指定订单
     *
     * @param session 当前用户
     * @param orderNo 订单号
     * @return 取消订单是否成功的响应对象。
     */
    @ResponseBody
    @RequestMapping(value = "cancel.do", method = RequestMethod.POST)
    public ServerResponse<String> cancel(HttpSession session, Long orderNo) {
        User user = (User) session.getAttribute(IConst.CURRENT_USER);
        if (user == null)
            return ServerResponse.createByErrorCode(ResponseInfo.NEED_LOGIN.getCode(), ResponseInfo.NEED_LOGIN.getDescription());
        return iOrderService.cancelOrder(user.getId(), orderNo);
    }

    /**
     * 这个方法主要用在获取订单支付页面关于订单信息的简易预览时的对象。
     *
     * @param session 当前用户
     * @param orderNo 订单号
     * @return 简易预览的订单商品信息
     */
    @ResponseBody
    @RequestMapping(value = "order_simple.do", method = RequestMethod.POST)
    public ServerResponse<OrderProductVo> orderSimple(HttpSession session, Long orderNo) {
        User user = (User) session.getAttribute(IConst.CURRENT_USER);
        if (user == null)
            return ServerResponse.createByErrorCode(ResponseInfo.NEED_LOGIN.getCode(), ResponseInfo.NEED_LOGIN.getDescription());
        return iOrderService.orderSimple(user.getId());
    }

    /**
     * 查询指定订单详情
     *
     * @param session 当前用户
     * @param orderNo 订单号
     * @return 订单详情VO对象
     */
    //关于@RequestParam这个注解的字段required。默认值为true,就是说要求传递一个值给这个参数，否则会报异常。
    //如果改为false，则如果没有传值，会将改值设为null。这也是不使用基本类型的原因，因为基本类型不能=null。
    //我在想的是，如果象这里一样直接使用@RequestParam默认注解，是不是可以减少方法中开始的空值判断。
    @ResponseBody
    @RequestMapping(value = "order_detail.do", method = RequestMethod.POST)
    public ServerResponse<OrderVo> getOrderDetail(@RequestParam HttpSession session, @RequestParam Long orderNo) {
        User user = (User) session.getAttribute(IConst.CURRENT_USER);
        if (user == null)
            return ServerResponse.createByErrorCode(ResponseInfo.NEED_LOGIN.getCode(), ResponseInfo.NEED_LOGIN.getDescription());
        return iOrderService.getOrderDetail(user.getId(), orderNo);
    }

    /**
     * 查询用户的所有订单信息并分页
     *
     * @param session  当前用户
     * @param pageNum  当前页码
     * @param pageSize 每页数量
     * @return 响应
     */
    @ResponseBody
    @RequestMapping(value = "list.do", method = RequestMethod.POST)
    public ServerResponse<PageInfo<OrderVo>> list(@RequestParam HttpSession session,
                                                  @RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum,
                                                  @RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize) {
        User user = (User) session.getAttribute(IConst.CURRENT_USER);
        if (user == null)
            return ServerResponse.createByErrorCode(ResponseInfo.NEED_LOGIN.getCode(), ResponseInfo.NEED_LOGIN.getDescription());
        return iOrderService.list(user.getId(), pageNum, pageSize);
    }


}
